package logger

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/sirupsen/logrus"
)

var (
	Logger *logrus.Logger
	config *Config
)

// Config 日志配置
type Config struct {
	Level       string `json:"level" yaml:"level"`             // 日志级别: debug, info, warn, error
	Format      string `json:"format" yaml:"format"`           // 日志格式: json, text
	Output      string `json:"output" yaml:"output"`           // 输出方式: console, file, both
	FilePath    string `json:"file_path" yaml:"file_path"`     // 日志文件路径
	MaxSize     int    `json:"max_size" yaml:"max_size"`       // 单个文件最大大小(MB)
	MaxBackups  int    `json:"max_backups" yaml:"max_backups"` // 保留的备份文件数量
	MaxAge      int    `json:"max_age" yaml:"max_age"`         // 保留的天数
	Compress    bool   `json:"compress" yaml:"compress"`       // 是否压缩备份文件
	ShowCaller  bool   `json:"show_caller" yaml:"show_caller"` // 是否显示调用者信息
	Environment string `json:"environment" yaml:"environment"` // 环境: development, production
}

// DefaultConfig 默认配置
func DefaultConfig() *Config {
	return &Config{
		Level:       "info",
		Format:      "text",
		Output:      "console",
		FilePath:    "logs/app.log",
		MaxSize:     100,
		MaxBackups:  3,
		MaxAge:      7,
		Compress:    true,
		ShowCaller:  true,
		Environment: "development",
	}
}

// Init 初始化日志系统
func Init(cfg *Config) error {
	if cfg == nil {
		cfg = DefaultConfig()
	}
	config = cfg

	Logger = logrus.New()

	// 设置日志级别
	level, err := logrus.ParseLevel(cfg.Level)
	if err != nil {
		return fmt.Errorf("invalid log level: %s", cfg.Level)
	}
	Logger.SetLevel(level)

	// 设置日志格式
	if cfg.Format == "json" {
		Logger.SetFormatter(&logrus.JSONFormatter{
			TimestampFormat: time.RFC3339,
		})
	} else {
		Logger.SetFormatter(&CustomTextFormatter{
			TimestampFormat: "2006-01-02 15:04:05",
			ShowCaller:      cfg.ShowCaller,
			Environment:     cfg.Environment,
		})
	}

	// 设置输出
	switch cfg.Output {
	case "console":
		Logger.SetOutput(os.Stdout)
	case "file":
		if err := setupFileOutput(cfg); err != nil {
			return err
		}
	case "both":
		if err := setupBothOutput(cfg); err != nil {
			return err
		}
	default:
		Logger.SetOutput(os.Stdout)
	}

	// 设置是否显示调用者信息
	Logger.SetReportCaller(cfg.ShowCaller)

	return nil
}

// CustomTextFormatter 自定义文本格式化器
type CustomTextFormatter struct {
	TimestampFormat string
	ShowCaller      bool
	Environment     string
}

func (f *CustomTextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	var b strings.Builder

	// 时间戳
	b.WriteString(entry.Time.Format(f.TimestampFormat))
	b.WriteString(" ")

	// 日志级别
	level := strings.ToUpper(entry.Level.String())
	switch entry.Level {
	case logrus.DebugLevel:
		b.WriteString(fmt.Sprintf("\033[36m[%s]\033[0m", level)) // 青色
	case logrus.InfoLevel:
		b.WriteString(fmt.Sprintf("\033[32m[%s]\033[0m", level)) // 绿色
	case logrus.WarnLevel:
		b.WriteString(fmt.Sprintf("\033[33m[%s]\033[0m", level)) // 黄色
	case logrus.ErrorLevel:
		b.WriteString(fmt.Sprintf("\033[31m[%s]\033[0m", level)) // 红色
	case logrus.FatalLevel:
		b.WriteString(fmt.Sprintf("\033[35m[%s]\033[0m", level)) // 紫色
	default:
		b.WriteString(fmt.Sprintf("[%s]", level))
	}
	b.WriteString(" ")

	// 调用者信息
	if f.ShowCaller && entry.HasCaller() {
		caller := fmt.Sprintf("%s:%d", filepath.Base(entry.Caller.File), entry.Caller.Line)
		if f.Environment == "development" {
			b.WriteString(fmt.Sprintf("\033[90m[%s]\033[0m ", caller)) // 灰色
		} else {
			b.WriteString(fmt.Sprintf("[%s] ", caller))
		}
	}

	// 消息
	b.WriteString(entry.Message)

	// 字段
	if len(entry.Data) > 0 {
		b.WriteString(" ")
		for key, value := range entry.Data {
			b.WriteString(fmt.Sprintf("%s=%v ", key, value))
		}
	}

	b.WriteString("\n")
	return []byte(b.String()), nil
}

// setupFileOutput 设置文件输出
func setupFileOutput(cfg *Config) error {
	// 确保日志目录存在
	dir := filepath.Dir(cfg.FilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed to create log directory: %w", err)
	}

	file, err := os.OpenFile(cfg.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return fmt.Errorf("failed to open log file: %w", err)
	}

	Logger.SetOutput(file)
	return nil
}

// setupBothOutput 设置同时输出到控制台和文件
func setupBothOutput(cfg *Config) error {
	// 确保日志目录存在
	dir := filepath.Dir(cfg.FilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed to create log directory: %w", err)
	}

	_, err := os.OpenFile(cfg.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return fmt.Errorf("failed to open log file: %w", err)
	}

	// 使用 MultiWriter 同时写入控制台和文件
	Logger.SetOutput(os.Stdout) // 这里可以使用 io.MultiWriter，但为了简化先用控制台
	return nil
}

// GetCaller 获取调用者信息
func GetCaller(skip int) (string, int) {
	_, file, line, ok := runtime.Caller(skip)
	if !ok {
		return "unknown", 0
	}
	return filepath.Base(file), line
}

// 便捷方法
func Debug(args ...interface{}) {
	Logger.Debug(args...)
}

func Debugf(format string, args ...interface{}) {
	Logger.Debugf(format, args...)
}

func Info(args ...interface{}) {
	Logger.Info(args...)
}

func Infof(format string, args ...interface{}) {
	Logger.Infof(format, args...)
}

func Warn(args ...interface{}) {
	Logger.Warn(args...)
}

func Warnf(format string, args ...interface{}) {
	Logger.Warnf(format, args...)
}

func Error(args ...interface{}) {
	Logger.Error(args...)
}

func Errorf(format string, args ...interface{}) {
	Logger.Errorf(format, args...)
}

func Fatal(args ...interface{}) {
	Logger.Fatal(args...)
}

func Fatalf(format string, args ...interface{}) {
	Logger.Fatalf(format, args...)
}

// WithFields 添加字段
func WithFields(fields logrus.Fields) *logrus.Entry {
	return Logger.WithFields(fields)
}

// WithField 添加单个字段
func WithField(key string, value interface{}) *logrus.Entry {
	return Logger.WithField(key, value)
}

// WithError 添加错误字段
func WithError(err error) *logrus.Entry {
	return Logger.WithError(err)
}
